/*
* tedi2html main code
* Copyright (C) <2022>  <alkeon> [alkeon@autistici.org]
   
* Texdi is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Texdi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with tedi2html.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>

#include "../tedi2lang/tedi2lang.h"
#include "tedi2html.h"
#include "../tedi2lang/exception.h"

using namespace std;

#define BLOCK 2
#define IMAGE 1
#define LINK 0
#define NO_TAG -1

tedi2html::tedi2html(tags_definition td): tedi2lang(td), _start_paragraph_tag("<p>"){}

tedi2html::tedi2html(): tedi2lang(default_tags_value()), _start_paragraph_tag("<p>"){}

tags_definition tedi2html::default_tags_value(){
	
	tags_definition td;

	td.start_heading_first_level_tag = "<h1>";
	td.start_heading_second_level_tag = "<h2>";
	td.start_heading_third_level_tag = "<h3>";
	td.start_heading_fourth_level_tag = "<h4>";

	td.end_heading_first_level_tag = "</h1>";
	td.end_heading_second_level_tag = "</h2>";
	td.end_heading_third_level_tag = "</h3>";
	td.end_heading_fourth_level_tag = "</h4>";

	td.start_list_tag = "<ul>";
	td.list_item_tag = "<li>";
	td.end_list_tag = "</ul>";

	td.start_container_tag = "<div class=\"";
	td.middle_container_tag = "\">";
	td.end_container_tag = "</div>";

	td.start_link_tag = "<a href=\"";
	td.middle_link_tag = "\">";
	td.end_link_tag = "</a>";

	td.start_image_tag = "<img alt=\"";
	td.middle_image_tag = "\" src=\"";
	td.end_image_tag = "\">";

	td.start_table_tag = "<table>";
	td.end_table_tag = "</table>";
	td.start_table_row_tag = "<tr>";
	td.end_table_row_tag = "</tr>";
	td.start_table_data_tag = "<td>";
	td.end_table_data_tag = "</td>";

	td.end_paragraph_tag = "</p>";

	return td;
}

/*
 * Add header, iterate through text and finish with footer
 *
 */
string tedi2html::convert(string text, string header, string footer) {

	stringstream index(text);
	string line, return_text = header;
	_open_brackets = 0;
	_is_paragraph = false;
	_is_converting_table = false;
	_is_unordered_list = 0;
	while(getline(index, line)){
		_has_block = false;
		return_text += convert_line(line);
	}
	
	if(_open_brackets > 0)
		throw Invalid("Missing '}' in document.", "End of file");

	if(_is_converting_table) return_text += _end_table_tag + "\n";
	if(_is_paragraph) return_text += _end_paragraph_tag + "\n";
	return_text += footer;

	return return_text;
}

/*
 * Deletes heading tag and insert HTML heading tag
 *
 */
string tedi2html::convert_line_heading(string& line, size_t hash_position) {

	int level = 0;
	while(found(hash_position) && line[hash_position + level] == '#')
		++level;
	
	if(hash_position + level >= line.size())
		throw Invalid("Unexpected heading size", line);
	else
		line = line.substr(hash_position + level, line.size() - 1);
	
	line = strip_escaping(line);
	switch(level){
		case 1: line = _start_heading_first_level_tag + line + _end_heading_first_level_tag; break;
		case 2: line = _start_heading_second_level_tag + line + _end_heading_second_level_tag; break;
		case 3: line = _start_heading_third_level_tag + line + _end_heading_third_level_tag; break;
		case 4: line = _start_heading_fourth_level_tag + line + _end_heading_fourth_level_tag; break;
		default: line = _start_heading_fourth_level_tag + line + _end_heading_fourth_level_tag; break;
	}
	
	return (close_paragraph(_is_paragraph) + line + "\n");
}

// List tags

string tedi2html::convert_line_list_start(string& line) {

	++_is_unordered_list;
	return close_paragraph(_is_paragraph) + _start_list_tag + "\n";
	
}

void tedi2html::convert_line_list_item(string& line, size_t li){

	line = line.erase(li, 2);
	line = line.insert(li, close_paragraph(_is_paragraph) + _list_item_tag);
	
}

string tedi2html::convert_line_list_end(string& line) {

	--_is_unordered_list;
	return close_paragraph(_is_paragraph) + _end_list_tag + "\n";
	
}

/*
 * Deletes block tag and insert block tag
 *
 */
void tedi2html::convert_line_block(string& line) {
	if(_is_paragraph){
		line = "</p>\n" + line;
		_is_paragraph = false;
	}
	size_t start_tag = get_not_escaped_tag(line, "{(");
	if(found(start_tag) && !is_tag_escaped(line, start_tag)) {
		line = line.erase(start_tag, 2);
		line = line.insert(start_tag, _start_container_tag);

		start_tag = get_not_escaped_tag(line, ") ");
		if(found(start_tag) && !is_tag_escaped(line, start_tag)) {
			line = line.erase(start_tag, 2);
			line = line.insert(start_tag, _middle_container_tag);

			size_t end_tag = correct_position(line, start_tag + _middle_container_tag.size(), '{', '}');
			if(found(end_tag)) {
				line = line.erase(end_tag, 1);
				line = line.insert(end_tag, _end_container_tag);
			} else
				++_open_brackets;
			
		} else
			throw Invalid("Missing ')' in block tag.",line);
	} else
		throw Invalid("Missing block tag.",line);

	_has_block = true;
}

/*
 * Start or continue table conversion
 *
 */
string tedi2html::convert_line_table(string& line, size_t first_pipe) {
	string return_text;
	if(!_is_converting_table) {
		if(first_pipe != line.rfind("|")) {
			return_text += close_paragraph(_is_paragraph) + _start_table_tag + "\n";
			_is_converting_table = true;
			return return_text + convert_line_table_row(line);
		} else
			return convert_line_ending(line);

	}else
		return return_text + convert_line_table_row(line);
}

/*
 * Check line ending and convert depending ending whitespace
 *
 */
string tedi2html::convert_line_ending(string& line){
	if(line.size() > 1){
		if(line[line.size() - 1] == ' '){
			if(_is_paragraph) {

				_is_paragraph = false;
				return strip_escaping(line) + _end_paragraph_tag + "\n";
			} else {
				if(!_is_converting_table && !_has_block && !_is_unordered_list)
					return _start_paragraph_tag + strip_escaping(line) + _end_paragraph_tag + "\n";
				else
					return strip_escaping(line) + "\n";
			}
		} else if(!_is_converting_table && !_has_block && !_is_unordered_list) {
			if(_is_paragraph)
				return strip_escaping(line) + "\n";
			else {

				_is_paragraph = true;
				return _start_paragraph_tag + strip_escaping(line) + "\n";
				
			}
		} else {
			
			if(_is_paragraph) {
				_is_paragraph = false;
				return _end_paragraph_tag + "\n" + strip_escaping(line) + "\n";

			} else
				return strip_escaping(line) + "\n";
		}
	} else 
		return line + "\n";
	
}

/*
 * Control tags:
 * <!, <>, <+. <
 */
string tedi2html::convert_line_control_tags(string& line){
	if(line[1] != '!') {
		if(line[1] == '>') {
			line = line.erase(0,2);
			return line + "\n";
		} else if(line[1] == '+') {
			line = line.erase(0,2);
			if(_is_paragraph) {
				_is_paragraph = false;
				return line + _end_paragraph_tag + "\n";

			} else
				return _start_paragraph_tag + line + _end_paragraph_tag + "\n";
			
		} else {
			line = line.erase(0,1);
			return line + "\n";
		}
	} else
		return "";
	
}

/*
 * If there's an open paragraph, close it
 *
 */
string tedi2html::close_paragraph(bool& is_paragraph){
	string p;
	if(is_paragraph){
		p = _end_paragraph_tag + "\n";
		is_paragraph = false;
	}
	return p;
}
